﻿// The Nova Project by Ken Beckett.
// Copyright (C) 2007-2012 Inevitable Software, all rights reserved.
// Released under the Common Development and Distribution License, CDDL-1.0: http://opensource.org/licenses/cddl1.php

using System.Collections.Generic;
using System.Windows.Media;

using Nova.CodeDOM;

namespace Nova.UI
{
    /// <summary>
    /// The view model for a <see cref="CodeDOM.ArgumentsOperator"/>.
    /// </summary>
    public abstract class ArgumentsOperatorVM : OperatorVM
    {
        #region /* FIELDS */

        protected ExpressionVM _expressionVM;
        protected ChildListVM<ExpressionVM> _argumentVMs;

        #endregion

        #region /* CONSTRUCTORS */

        /// <summary>
        /// Create a view model instance for the specified <see cref="CodeDOM.ArgumentsOperator"/>.
        /// </summary>
        protected ArgumentsOperatorVM(ArgumentsOperator argumentsOperator, Dictionary<CodeObject, CodeObjectVM> dictionary)
            : base(argumentsOperator, dictionary)
        {
            _expressionVM = (ExpressionVM)CreateVM(argumentsOperator.Expression, false, dictionary);
            _argumentVMs = CreateListVM<Expression, ExpressionVM>(argumentsOperator.Arguments, dictionary);
        }

        #endregion

        #region /* PROPERTIES */

        /// <summary>
        /// The underlying <see cref="CodeDOM.ArgumentsOperator"/> model.
        /// </summary>
        public ArgumentsOperator ArgumentsOperator
        {
            get { return (ArgumentsOperator)CodeObject; }
        }

        /// <summary>
        /// The <see cref="ExpressionVM"/> being invoked.
        /// </summary>
        public virtual new ExpressionVM Expression
        {
            get { return _expressionVM; }
        }

        /// <summary>
        /// The argument expressions.
        /// </summary>
        public ChildListVM<ExpressionVM> Arguments
        {
            get { return _argumentVMs; }
        }

        /// <summary>
        /// True if there are any arguments.
        /// </summary>
        public bool HasArguments
        {
            get { return (_argumentVMs != null && _argumentVMs.Count > 0); }
        }

        /// <summary>
        /// The number of arguments.
        /// </summary>
        public int ArgumentCount
        {
            get { return (_argumentVMs != null ? _argumentVMs.Count : 0); }
        }

        #endregion

        #region /* METHODS */

        #endregion

        #region /* RENDERING */

        protected abstract void RenderName(CodeRenderer renderer, RenderFlags flags);

        protected override Brush RenderBrush(RenderFlags flags)
        {
            return PUNC_BRUSH;
        }

        public override void RenderExpression(CodeRenderer renderer, RenderFlags flags)
        {
            RenderFlags passFlags = (flags & RenderFlags.PassMask);
            bool attributeCall = flags.HasFlag(RenderFlags.Attribute);

            RenderName(renderer, passFlags | (flags & RenderFlags.Attribute));  // Special case - allow the Attribute flag to pass
            if ((_argumentVMs != null && _argumentVMs.Count > 0) || (!flags.HasFlag(RenderFlags.NoParensIfEmpty) && !attributeCall) || ArgumentsOperator.HasInfixComments)
            {
                Brush brush = RenderBrush(flags);
                RenderStartArguments(renderer, brush, flags);
                RenderInfixComments(renderer, 0, flags);
                renderer.RenderList(_argumentVMs, passFlags | RenderFlags.ForceBorder, this);
                RenderEndArguments(renderer, brush, flags);
            }
            RenderInitializer(renderer, passFlags);
        }

        protected abstract void RenderStartArguments(CodeRenderer renderer, Brush brush, RenderFlags flags);
        protected abstract void RenderEndArguments(CodeRenderer renderer, Brush brush, RenderFlags flags);

        protected virtual void RenderInitializer(CodeRenderer renderer, RenderFlags flags)
        { }

        public override void RenderVisible(CodeRenderer renderer, RenderFlags flags)
        {
            base.RenderVisible(renderer, flags);
            if (_expressionVM != null)
                _expressionVM.RenderVisible(renderer, flags);
            renderer.RenderVisibleList(_argumentVMs, flags);
        }

        public override void UnRender()
        {
            if (_expressionVM != null)
                _expressionVM.UnRender();
            ChildListHelpers.UnRender(_argumentVMs);
            base.UnRender();
        }

        #endregion
    }
}
